/*Test module used to support pico.dll Bus/Master test.
- Version = 3.9.0.0

 Module implements a 32bit counter which is accessed using Bus Mastering or single word I/O.
 Counter increments when read, or adds data from bus to counter on write. 

 Read Status port returns:
     0x000FFFFF = number of 32bit words available to be read.
     0xFC000000 = 0x26 (signature)
 Write Status port returns:
     0x000FFFFF = number of 32bit words that may be written.
     0xFC000000 = 0x22 (signature)
 Statuses sometimes returns zero for # words available to simulate not ready conditions.
 
 The signals PicoAddr, PicoDataIn, PicoRd, and PicoWr can be used to access
 a single memory mapped 'device', or they can be used for Bus Mastering I/O.
 The logic which generates the PicoXXX signals provides a consistent bus interface 
 for I/O burst or single word access to the device.

 The interface can be accessed using standard read and write functions (see Picodll.chm or PicoDll.pdf).
*/

`include "PicoDefines.v"

module BMTestCounter#(
   parameter C_CARDBUS_WIDTH = 32
 ) (
   input                        PicoRst,
   output [C_CARDBUS_WIDTH-1:0] PicoDataOut,       //data returned
   input  [C_CARDBUS_WIDTH-1:0] PicoAddr,          //address from BM/PCMCIA bus   
   input  [C_CARDBUS_WIDTH-1:0] PicoDataIn,        //data    from BM/PCMCIA
   input                        PicoRd,            //IO Read from BM/PCMCIA bus
   input                        PicoWr,            //IO Write to  BM/PCMCIA bus
   input                        PicoClk            //CardBus clock
 );

//BMTEST CHANNEL (1)
`define BMTEST_CHANNEL           1
`define BMTEST_DATA_ADR         `BM_ADDR_FROM_CHANNEL(`BMTEST_CHANNEL)       //address of data for BMTEST
`define BMTEST_READ_STATUS_ADR  (`BM_STATUS_FROM_CHANNEL(`BMTEST_CHANNEL))   //address of read status  for BMTEST
`define BMTEST_WRITE_STATUS_ADR (`BM_STATUS_FROM_CHANNEL(`BMTEST_CHANNEL)+4) //address of write status for BMTEST

//----------------- BMtest counter address decoding --------------------------------------------
//The counter is being accessed when PicoAddr is in the range [BMTEST_DATA_ADR, .+0xFFFFF]
//ie ignore the bottom 20 bits.
wire   bmTestData_selected, bmTestData_read, bmTestData_write;
assign bmTestData_selected = ({PicoAddr[C_CARDBUS_WIDTH-1:20], 20'b0} == `BMTEST_DATA_ADR);
assign bmTestData_read     = (bmTestData_selected & PicoRd);  //cardbus read  data
assign bmTestData_write    = (bmTestData_selected & PicoWr);  //cardbus write data

//----------------- BMtest status address decoding ---------------------------------------------
wire   bmTestStat_selectR, bmTestStat_read, bmTestStat_selectW, bmTestStat_write;
assign bmTestStat_selectR = ({PicoAddr[C_CARDBUS_WIDTH-1:2], 2'b0} == `BMTEST_READ_STATUS_ADR);
assign bmTestStat_selectW = ({PicoAddr[C_CARDBUS_WIDTH-1:2], 2'b0} == `BMTEST_WRITE_STATUS_ADR);
assign bmTestStat_read    = (bmTestStat_selectR & PicoRd);    //cardbus read status
assign bmTestStat_write   = (bmTestStat_selectW & PicoRd);    //cardbus write status

reg [C_CARDBUS_WIDTH-1:0] bmTestCounter=0;
reg                       bmSometimes;
reg                       bmAlways=0;

//-----------------  reading from bmTestCounter -----------------------------------------------
always @(posedge PicoClk)
   begin
   if (bmTestData_read)                     bmTestCounter <= bmTestCounter + 1;          else
   if (bmTestData_write)                    bmTestCounter <= bmTestCounter + PicoDataIn; else
   if (bmTestStat_read || bmTestStat_write) bmSometimes   <= !bmSometimes;               
   //write to status+8 sets bmAlway. Allows us to force ready always for speed tests.
   else if (({PicoAddr[C_CARDBUS_WIDTH-1:2], 2'b0} == `BMTEST_READ_STATUS_ADR+8) && PicoWr) bmAlways <= PicoDataIn[0];
   end

assign PicoDataOut = 
    (bmTestData_read  ? bmTestCounter                                                                    : 0) |
    (bmTestStat_read  ? {`BM_READ_STATUS_SIGNATURE,  6'h0, ((bmSometimes | bmAlways) ? 20'hFFFFF : 20'h0)} : 0) |   
    (bmTestStat_write ? {`BM_WRITE_STATUS_SIGNATURE, 6'h0, ((bmSometimes | bmAlways) ? 20'hFFFFF : 20'h0)} : 0);   

endmodule

